#pragma once 


#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>


// 这里实现的协议: 实现一个计算器, 客户端输入，服务器返回一个结果


//    用户向客户端输入int x=1, int y=2, char op='+'
// 1. 客户端使用Request  中 Serialize   将【结构化数据】序列化为协议规定的【字符串】, 给服务器
// 2. 服务器使用Request  中 Deserialize 将【字符串】反序列化为【结构化数据】，得到int result=3, int code=1
// 3. 服务器使用Response 中 Serialize   将【结构化数据】序列化为协议规定的【字符串】, 给客户端
// 4. 客户端使用Response 中 Deserialize 将【字符串】反序列化为【结构化数据】，输出结果


//【注意协议客户端和服务器都要遵守】
// 举例: int x=1, int y=2, char op='+' -> "length\r\nx_ op_ y_\r\n" ,
// 转为字符串时lenth是报文"x_ op_ y_"长度, \r\n分开长度length和报文x_ op_ y_, 报文x,op,y空格分开
// 【那么】服务器是不是就可以根据这种具有某种特征的字符串, 设计算法将其分开,拿到x, op ,y 需要的数据呢

namespace my_protocol
{
    #define SPACE " "
    #define SPACE_LEN strlen(SPACE)
    #define SEP "\r\n"
    #define SEP_LEN strlen(SEP) // 不能是sizeof！
    class Request
    {
    public:
        
        std::string Serialize() // 将结构化数据转为字符串:比如 "length\r\nx_ op_ y_\r\n"  
        {
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter writer;
            return writer.write(root);
        }
        
        bool Deserialize(const std::string& str) // 将字符串转为结构化数据
        {
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();

        }
    public:
        Request()
        {}
        Request(int x, int y, char op):_x(x),_y(y),_op(op)
        {}
        ~Request()
        {}
    public:
        int _x;
        int _y;
        char _op; // +， -， *， /， %
    };

    class Response
    {
    public:
        std::string Serialize()
        {
            Json::Value root;
            root["code"] = _code;
            root["result"] = _result;
            Json::FastWriter writer;
            return writer.write(root);
        }

        bool Deserialize(const std::string& str)
        {
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
    public:
        Response()
        {}
       Response(int result, int code) 
        : _result(result), _code(code)
        {

        }
        ~Response()
        {}

    public:
        int _result; // 计算结果
        int _code; // 计算结果的状态码
    };

    // std::string *out 输出性参数
    bool Recv(int sock, std::string *out)
    {
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer)-1, 0); 
        if (s > 0)
        {
            buffer[s] = 0;
            *out += buffer;
        }
        else if (s == 0) // 写端关闭
        {
            // std::cout << "client quit" << std::endl;
            return false;
        }
        else
        {
            // std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }

    void Send(int sock, const std::string str)
    {
        int n = send(sock, str.c_str(), str.size(), 0);
        if (n < 0) // 读端关闭
            std::cout << "send error" << std::endl;
    }

    std::string Decode(std::string &buffer)
    {
        std::size_t pos = buffer.find(SEP);
        if(pos == std::string::npos) return "";
        int size = atoi(buffer.substr(0, pos).c_str());
        int surplus = buffer.size() - pos - 2*SEP_LEN;
        if(surplus >= size)
        {
            //至少具有一个合法完整的报文, 可以动手提取了
            buffer.erase(0, pos+SEP_LEN);
            std::string s = buffer.substr(0, size);
            buffer.erase(0, size + SEP_LEN);
            return s;
        }
        else
        {
            return "";
        }
    }

    // "XXXXXX"  ->  "123\r\nXXXXXX\r\n"
    std::string Encode(std::string &s)
    {
        std::string new_package = std::to_string(s.size());
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        // std::cout<<new_package<<std::endl;
        return new_package;
    }
}